/*************************************************************************
	> File Name: test.cc
	> Author: likang
	> Mail:  
	> Created Time: 2014年12月29日 星期一 11时02分34秒
 ************************************************************************/

#include<iostream>
#include<cstdarg>
#include "Python.h"
using namespace std;

//pyfile 要执行的python文件，func 代表要执行的函数，argc 代表要调用函数的参数个数， 
//p 代表参数的类型的指针, q代表参数的值的指针
int call_funbyName(string pyfile, string func, int num, string *p, ...) {
	
	//初始化Python
	Py_Initialize();
	//检查初始化是否成功
	if (!Py_IsInitialized()) {
		cout << "python initial failed!" << endl;
		return -1;
	}
    //添加当前路径
	PyRun_SimpleString("import sys");
	PyRun_SimpleString("sys.path.append('./')");
	va_list var_arg;
	va_start(var_arg,num);

	PyObject *pName, *pModule, *pDict, *pFunc, *pArgs;

	//载入名为pytest的脚本
	pName = PyString_FromString(pyfile.c_str());
	pModule = PyImport_Import(pName);
	if (!pModule) {
		cout << "can not find " << pyfile << endl;
		return -1;
	}
	pDict = PyModule_GetDict(pModule);
	if (!pDict) {
		return -1;
	}

	pFunc = PyDict_GetItemString(pDict,func.c_str());
	if (!pFunc || !PyCallable_Check(pFunc)) {
		cout << "can not find function " << func << endl;
		return -1;
	}
	//参数进栈
	pArgs = PyTuple_New(num);
	/**********************************************************************
	 * PyObject* Py_BuildValue(char *format,...)把C++的变量转换成一个Python
	 * 对象，当需要从C++传递变量到Python时，就会使用这个函数。此函数有点类似
	 * C的printf，但格式不同。常用的格式有s表示字符串，i表示整型变量，f表
	 * 示浮点数，O表示一个Python对象
	 *********************************************************************/
	for (int i = 0; i < num; ++i) {

		cout << "**" << p[i] << endl;
		if (p[i] == "i") {

			int value = va_arg(var_arg,int);
			cout << "value: " << value << endl;
			PyTuple_SetItem(pArgs,i,Py_BuildValue(p[i].c_str(),value));
		}
		else if (p[i] == "s") {
			char *value = va_arg(var_arg,char *);
			PyTuple_SetItem(pArgs,i,Py_BuildValue(p[i].c_str(),value));
		}
	}
	va_end(var_arg);
	//PyTuple_SetItem(pArgs,1,Py_BuildValue("i",4));
	//调用Python函数
	PyObject_CallObject(pFunc,pArgs);

	Py_DECREF(pName);
	Py_DECREF(pArgs);
	Py_DECREF(pModule);
	Py_DECREF(pFunc);
	Py_DECREF(pDict);
	//关闭python
	Py_Finalize();
}

int main(void) {
	string pyfile = "pytest";
	string func = "modifystr";
	int argc = 1;
	string p[] = {"s"};
	int q[] = {2,3};
	call_funbyName(pyfile,func,argc,p,"hello");
	string p1[] = {"i","i"};
	func = "add";
	argc = 2;
	call_funbyName("pytest","add",argc,p1,5,5);
	return 0;
}


	

